package cxm.proj.sms;

import java.io.File;
import java.io.FileInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

import android.app.AlertDialog;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView;
import android.widget.TabHost;
import android.widget.TabHost.TabSpec;
import android.widget.TextView;
import cxm.com.util.MyDownloader;
import cxm.com.util.MyLog;

public class MainActivity extends FragmentActivity {
	public MyDownloader xmlDownloader = null;
	public MyDownloader updateDownloader = null;
	FragmentTabHost mTabHost;
	int currentTab = 0;
	
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // setup tabhost
        mTabHost = (FragmentTabHost)findViewById(android.R.id.tabhost);
        mTabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);
        // get image size to set TabHost size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
        Bitmap bmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.control_select, o);
        mTabHost.getTabWidget().getLayoutParams().width = 4 * (bmp.getWidth());
        mTabHost.getTabWidget().getLayoutParams().height = bmp.getHeight();
        
        // add send fragment
        TabSpec spec = mTabHost.newTabSpec("Send");
        // create indicator view
        LayoutInflater inflater = (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
        View view = inflater.inflate(R.layout.tabind_send, null);
        ImageView img = (ImageView)view.findViewById(R.id.tabind_img_enable);
        img.setVisibility(View.VISIBLE);
        img.setImageResource(R.drawable.send_select);
        img = (ImageView)view.findViewById(R.id.tabind_img_disable);
        img.setImageResource(R.drawable.send_unselect);
        img.setVisibility(View.INVISIBLE);
        TextView text = (TextView)view.findViewById(R.id.tabind_text);
        text.setText(R.string.tab_send);
        // add indicator
        spec.setIndicator(view);
        mTabHost.addTab(spec, SendSMSFragment.class, null);
        
        // add control fragment
        spec = mTabHost.newTabSpec("control");
        view = inflater.inflate(R.layout.tabind_send, null);
        img = (ImageView)view.findViewById(R.id.tabind_img_enable);
        img.setImageResource(R.drawable.control_select);
        img = (ImageView)view.findViewById(R.id.tabind_img_disable);
        img.setImageResource(R.drawable.control_unselect);
        text = (TextView)view.findViewById(R.id.tabind_text);
        text.setText(R.string.tab_control);
        spec.setIndicator(view);
        mTabHost.addTab(spec, ControlFragment.class, null);
        
        // add how to fragment
        spec = mTabHost.newTabSpec("howto");
        view = inflater.inflate(R.layout.tabind_send, null);
        img = (ImageView)view.findViewById(R.id.tabind_img_enable);
        img.setImageResource(R.drawable.control_select);
        img = (ImageView)view.findViewById(R.id.tabind_img_disable);
        img.setImageResource(R.drawable.control_unselect);
        text = (TextView)view.findViewById(R.id.tabind_text);
        text.setText(R.string.tab_howto);
        spec.setIndicator(view);
        mTabHost.addTab(spec, HowToFragment.class, null);
        
        // add info fragment
        spec = mTabHost.newTabSpec("info");
        view = inflater.inflate(R.layout.tabind_send, null);
        img = (ImageView)view.findViewById(R.id.tabind_img_enable);
        img.setImageResource(R.drawable.info_select);
        img = (ImageView)view.findViewById(R.id.tabind_img_disable);
        img.setImageResource(R.drawable.info_unselect);
        text = (TextView)view.findViewById(R.id.tabind_text);
        text.setText(R.string.tab_info);
        spec.setIndicator(view);
        mTabHost.addTab(spec, InfoFragment.class, null);
        // set focus
        mTabHost.setCurrentTab(0);
        mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener(){
        	  @Override
        	  public void onTabChanged(String tabId) {
        		  int tab = mTabHost.getCurrentTab();
        		  for (int i = 0; i < mTabHost.getTabWidget().getTabCount(); i++) {
        			  View enableView = mTabHost.getTabWidget().getChildAt(i).findViewById(
        					  R.id.tabind_img_enable);
        			  View disableView = mTabHost.getTabWidget().getChildAt(i).findViewById(
        					  R.id.tabind_img_disable);
        			  if (tab == i) {
        				  enableView.setVisibility(View.VISIBLE);
        				  disableView.setVisibility(View.INVISIBLE);
        			  } else {
        				  enableView.setVisibility(View.INVISIBLE);
        				  disableView.setVisibility(View.VISIBLE);
        			  }
        		  }
        		  // fade animation trigger
        		  Animation fadeIn = new AlphaAnimation(0, 1);
        		  fadeIn.setInterpolator(new DecelerateInterpolator()); //add this
        		  fadeIn.setDuration(240);
        		  findViewById(R.id.realtabcontent).setAnimation(fadeIn);
        	  }
        });
        
        // construct xml downloader for upgrade
        String upgradeServer = Configure.getInstance().getConfigString(
				Configure.ConfigureOption.UpgradeServer);
        String packageName = this.getPackageName();
        this.xmlDownloader = new MyDownloader(this,
        		"http://" + upgradeServer + "/" + packageName + "/update.xml", "update.xml");
        this.xmlDownloader.enableNotification(false);
        // if xml file download complete, construct upgrade download
        if (DownloadManager.STATUS_SUCCESSFUL ==
        		this.xmlDownloader.queryDownloadStatus())
        	this.analysisUpdateXml();
	}
	
	@Override
    public void onResume() {
		super.onResume();
		// register receiver
		this.registerReceiver(mReceivedDownloadReceiver, new IntentFilter(
				DownloadManager.ACTION_DOWNLOAD_COMPLETE));
		// first check apk file download to setup
		if (null != this.updateDownloader) {
			// read version from update xml
			String version = this.getUpgradeXmlNode(
					this.xmlDownloader.getDownloadFile(), "version");
			if ("" == version) {
				Log.d("MainActivity", "Get version from update xml fail");
				return;
			}
			// read download uri from update xml
			String uri = this.getUpgradeXmlNode(this.xmlDownloader.getDownloadFile(), "apk");
			if ("" == uri) {
				Log.e("MainActivity", "Cannot get download path from update xml");
				return;
			}

			// get current version
			String currentVersion = null;
			try {
				PackageInfo manager = this.getPackageManager().getPackageInfo(
						this.getPackageName(), 0);
				Log.d("MainActivity", "Compare version " + version +
						" To " + manager.versionName);
				currentVersion = manager.versionName;
			} catch (Exception e) {
				Log.d("MainActivity", "Cannot found package name");
				return;
			}
	    	// check version
	    	if (version.compareTo(currentVersion) > 0 &&
	    			(DownloadManager.STATUS_SUCCESSFUL ==
					this.updateDownloader.queryDownloadStatus()))
		    	// check download status to download
				this.displayAlert();
		} else {
			// check update xml download status
			if (DownloadManager.STATUS_SUCCESSFUL ==
					this.xmlDownloader.queryDownloadStatus())
				// if xml downloaded, fire apk downloading
				this.analysisUpdateXml();
			else
				this.xmlDownloader.startDownload();
				
		}
		Log.d("MainActivity", "Finish onResume");
    }
	
    @Override
    public void onPause() {
    	super.onPause();
    	MyLog.Log(MyLog.Level.Debug, "Start onPause");
    	
    	// unregister network receiver
    	this.unregisterReceiver(mReceivedDownloadReceiver);
    	
    	// compare version for clean
    	int status = this.xmlDownloader.queryDownloadStatus();
        MyLog.Log(MyLog.Level.Debug, "Status: " + status);
        if (DownloadManager.STATUS_SUCCESSFUL == status) {
        	// clear previous download if version is same as current version
        	String version = this.getUpgradeXmlNode(
        			this.xmlDownloader.getDownloadFile(), "version");
        	// compare with current apk
        	try {
    	    	PackageInfo manager = this.getPackageManager().getPackageInfo(
    	    			this.getPackageName(), 0);
    	    	if (version.compareTo(manager.versionName) > 0)
    	    		return;
        	} catch (Exception e) {
        		Log.d("MainActivity", "Cannot found package name");
        	}
        	this.xmlDownloader.clear();
        	if (null != this.updateDownloader)
        		this.updateDownloader.clear();
        }
    }
    
    // analysis xml file after download complete
    private void analysisUpdateXml() {
    	// read version from update xml
    	String version = this.getUpgradeXmlNode(
    			this.xmlDownloader.getDownloadFile(), "version");
    	if ("" == version) {
    		Log.d("MainActivity", "Get version from update xml fail");
    		return;
    	}
    	// read download uri from update xml
    	String uri = this.getUpgradeXmlNode(this.xmlDownloader.getDownloadFile(), "apk");
    	if ("" == uri) {
    		Log.e("MainActivity", "Cannot get download path from update xml");
    		return;
    	}

    	// get current version
    	String currentVersion = null;
    	try {
	    	PackageInfo manager = this.getPackageManager().getPackageInfo(
	    			this.getPackageName(), 0);
    		Log.d("MainActivity", "Compare version " + version +
    				" To " + manager.versionName);
    		currentVersion = manager.versionName;
    	} catch (Exception e) {
    		Log.d("MainActivity", "Cannot found package name");
    		return;
    	}

    	// construct update downloader
    	this.updateDownloader = new MyDownloader(this, uri, this.getPackageName() + ".apk");

    	// check version
    	if (version.compareTo(currentVersion) <= 0) {
    		MyLog.Log(MyLog.Level.Info, "Version compared, no need for update");
    		return;
    	}
    	// check download status to download
        if (DownloadManager.STATUS_SUCCESSFUL !=
        		this.updateDownloader.queryDownloadStatus())
	    	this.updateDownloader.startDownload();
    }
    
    private String getUpgradeXmlNode(File file, String nodeString) {
    	try {
	    	DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
	    	DocumentBuilder builder = factory.newDocumentBuilder();
	    	Document dom = builder.parse(new InputSource(new FileInputStream(file)));
	    	Node node = dom.getDocumentElement().getElementsByTagName(nodeString).item(0);
	    	
	    	return node.getTextContent();
    	} catch (Exception e) {
    		Log.d("MainActivity", "Cannot get xml node " + nodeString + " :" + e);
        	return "";
    	}
    }
    
    private void displayAlert() {
    	int status = this.updateDownloader.queryDownloadStatus();
    	if (DownloadManager.STATUS_SUCCESSFUL != status) {
    		MyLog.Log(MyLog.Level.Error, "Display dialog with wrong status: " + status);
    		return;
    	}
    	
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle(this.getString(R.string.main_download));
        builder.setMessage(this.getString(R.string.main_download_verbose));
        builder.setPositiveButton(this.getString(R.string.main_download_yes),
    		new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
            	Intent promptInstall = new Intent(Intent.ACTION_VIEW)
                .setDataAndType(Uri.fromFile(updateDownloader.getDownloadFile()),
                                "application/vnd.android.package-archive");
            	startActivity(promptInstall); 
            }
        });
        builder.setNegativeButton(this.getString(R.string.main_download_no),
    		new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
            }
        });
        AlertDialog alert = builder.create();
        alert.show();
        MyLog.Log(MyLog.Level.Debug, "Show download complete dialog to user");
    }
    
    private void onDownloadComplete() {
    	if (null == this.updateDownloader)
    		// xml download complete
    		this.analysisUpdateXml();
    	else
    		this.displayAlert();
    }
    
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            new AlertDialog.Builder(this).setTitle(this.getString(R.string.errmsg_exit))
            .setMessage(this.getString(R.string.errmsg_exit_verbose))
            .setPositiveButton(this.getString(R.string.errmsg_yes),
            	new DialogInterface.OnClickListener() {
                // do something when the button is clicked
                public void onClick(DialogInterface arg0, int arg1) {
                    finish();
                }
            })
            .setNegativeButton(this.getString(R.string.errmsg_no),
            	new DialogInterface.OnClickListener() {
                // do something when the button is clicked
                public void onClick(DialogInterface arg0, int arg1) {
                	// remain empty
                }
            }).show();
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    private final BroadcastReceiver mReceivedDownloadReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (!action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
            	return;
            
            // displayAlert();
            onDownloadComplete();
        }
    };
}
